﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Shell.KnowledgeBase
{
    public static class ReadingModule
    {
        public static Statement ToStatementLetterwise(this string value, IDictionary<string, Variable> variableMap)
        {
            return new Statement(
                ProcessSubstring(value, variableMap).ToArray());
        }

        private static IEnumerable<Term> ProcessSubstring(string value, IDictionary<string, Variable> variableMap)
        {
            var i = 0;

            while (i < value.Length)
            {
                char c = value[i];

                if (c == '#')
                {
                    var index = FindNextSpace(value, i);
                    var name = value.Substring(i + 1, index - i - 1);
                    i = index;
                    yield return new Atom(name);
                }
                else if (c == '%')
                {
                    var index = FindNextSpace(value, i);
                    var name = value.Substring(i + 1, index - i - 1);
                    i = index;

                    if (variableMap.ContainsKey(name))
                    {
                        yield return variableMap[name];
                    }
                    else
                    {
                        var result = new Variable(name);
                        variableMap.Add(name, result);
                        yield return result;
                    }
                }
                else if (c == '(')
                {
                    var index = FindClosingBracket(value, i + 1);
                    var substring = value.Substring(i + 1, index - i - 1);

                    i = index + 1;

                    yield return new Statement(
                        ProcessSubstring(substring, variableMap));
                    
                }
                else
                {
                    yield return new Atom(value[i++].ToString());
                }
            }
        }

        private static int FindClosingBracket(string value, int start)
        {
            var depth = 1;
            var i = start;

            while (true)
            {
                if (i >= value.Length)
                {
                    throw new Exception("Unbalanced brackets in string: " + value);
                }

                if (value[i] == '(')
                {
                    depth++;
                }
                else if (value[i] == ')')
                {
                    depth--;
                }

                if (depth == 0)
                {
                    return i;
                }
                i++;
            }
        }

        private static int FindNextSpace(string value, int i)
        {
            var index = value.IndexOf(' ', i + 1);
            index = index != -1 ? index : value.Length;
            return index;
        }
    }
}